home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / KPlib 1.2.1 / sample_progs / cols.cxx < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-07  |  4.5 KB  |  142 lines  |  [TEXT/R*ch]

  1. /*
  2.     This program accepts a list of tokens via standard in, and sends
  3.     them to standard out in formatted columns.  The ordering of the
  4.     tokens in the columns is `natural'.  That is, they are arranged
  5.     top-to-bottom, and then left-to-right.  The screen width can be
  6.     specified with the `-w<width>' option (default is 80).  the number
  7.     of columns to display is chosen accordingly.
  8.  
  9.     Written by Keith Pomakis on October 14, 1994.  Public Domain.
  10. */
  11.  
  12. #include <iostream.h>
  13. #include <strstream.h>
  14. #include <ctype.h>
  15. #include "../KPbasic.h"
  16. #include "../KPList.h"
  17. #include "../KPArray.h"
  18. #include "../KPString.h"
  19.  
  20. const char *const help_string =
  21.     "This program accepts a list of tokens via standard in, and sends\n"
  22.     "them to standard out in formatted columns.  The ordering of the\n"
  23.     "tokens in the columns is `natural'.  That is, they are arranged\n"
  24.     "top-to-bottom, and then left-to-right.  The screen width can be\n"
  25.     "specified with the `-w<width>' option (default is 80).  the number\n"
  26.     "of columns to display is chosen accordingly.\n\n"
  27.     "Written by Keith Pomakis on October 14, 1994.  Public Domain.\n";
  28.  
  29. static inline KPString
  30. base(const KPString &string)
  31. {
  32.     KPList<KPString> components;
  33.     components = string.tokens('/');
  34.     return components.tail();
  35. }
  36.  
  37. int
  38. main(int argc, char *argv[])
  39. {
  40.     int screen_width;
  41.     KPString progname = base(argv[0]);
  42.     KPString usage_string;
  43.     usage_string << "Usage: " << progname << " -w<width>\n"
  44.                  << "       " << progname << " -help\n";
  45.  
  46.     if (argc > 2 || (argc == 2 && (argv[1][0] != '-'))) {
  47.         cerr << usage_string;
  48.         exit(EXIT_FAILURE);
  49.     }
  50.  
  51.     if (argc == 2)
  52.         switch(argv[1][1]) {
  53.             case 'h':
  54.                 cout << help_string;
  55.                 exit(EXIT_SUCCESS);
  56.                 break;
  57.             case 'w':
  58.                 if (!isdigit(argv[1][2])) {
  59.                     cerr << usage_string;
  60.                     exit(EXIT_FAILURE);
  61.                 }
  62.                 else {
  63.                     istrstream strin(&argv[1][2]);
  64.                     strin >> screen_width;
  65.                 }
  66.                 break;
  67.             default:
  68.                 cerr << usage_string;
  69.                 exit(EXIT_FAILURE);
  70.         }
  71.     else
  72.         screen_width = 80;
  73.  
  74.     KPList<KPString> tokens;
  75.     KPString input_token;
  76.     int max_length = 0;
  77.     int i, j, k;
  78.     const int min_separation = 2;
  79.  
  80.     // Read the tokens into a list.
  81.     while (!cin.eof()) {
  82.         input_token.read_token(cin);
  83.         if (!cin.eof()) {
  84.             if (input_token.length() > screen_width - min_separation)
  85.                 input_token.cut(screen_width - min_separation);
  86.             max_length = max(max_length, input_token.length());
  87.             tokens += input_token;
  88.         }
  89.     }
  90.  
  91.     // Figure out how to display them.
  92.     const int potential_cols = screen_width / (max_length + min_separation);
  93.     const int rows = (tokens.size() + potential_cols - 1 ) / potential_cols;
  94.     const small_row_size = tokens.size() / rows;
  95.     const int cols = (small_row_size*rows == tokens.size())?
  96.                                     small_row_size : small_row_size + 1;
  97.     const int full_rows = (tokens.size()%rows == 0)? rows : tokens.size()%rows;
  98.     const int full_cols = (rows == full_rows)? cols : cols - 1;
  99.     const int col_width = screen_width / cols;
  100.  
  101.     KPReadOnlyIterator<KPString> iter(tokens);
  102.  
  103.     // Using column-oriented indexing.  Read the tokens into the structure.
  104.     KPArray< KPArray<KPString> > structure(cols);
  105.     for (i = 0; i < full_cols; i++) {
  106.         structure[i].resize(rows);
  107.         for (j = 0; j < rows; j++) {
  108.             structure[i][j] = *iter;
  109.             iter++;
  110.         }
  111.     }
  112.     if (cols != full_cols) {
  113.         structure[cols-1].resize(full_rows);
  114.         for (j = 0; j < full_rows; j++) {
  115.             structure[cols-1][j] = *iter;
  116.             iter++;
  117.         }
  118.     }
  119.  
  120.     // Print out the structure.
  121.     for (j = 0; j < full_rows; j++) {
  122.         for (i = 0; i < cols; i++) {
  123.             cout << structure[i][j];
  124.             if (i < cols - 1)
  125.                 for (k = structure[i][j].length(); k < col_width; k++)
  126.                     cout << ' ';
  127.         }
  128.         cout << '\n';
  129.     }
  130.     for (j = full_rows; j < rows; j++) {
  131.         for (i = 0; i < full_cols; i++) {
  132.             cout << structure[i][j];
  133.             if (i < full_cols - 1)
  134.                 for (k = structure[i][j].length(); k < col_width; k++)
  135.                     cout << ' ';
  136.         }
  137.         cout << '\n';
  138.     }
  139.  
  140.     return 0;
  141. }
  142.